'use client';

import { type ChangeEvent, type FormEvent, useEffect, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  querySubmenuDetails,
  removeSubmenu,
  updateSubmenu,
} from '@/services/api';
import type { TBody, TMenuMenuType } from '@/types';
import classNames from 'classnames';
import type {
  IDifference,
  IMenu,
  ISubmenu,
  IUpdateMenuBody,
} from '@/interfaces';
import diff from 'microdiff';
import { MENU_TYPE_KEY } from '@/lib/constant';
import useToast from '@/hooks/useToast';
import { getDiffData, getFilterData, isEmpty } from '@/lib/tool';

export default function UpdateMenuSubmenu(
  this: any,
  {
    details,
  }: {
    details: IMenu;
  },
) {
  const { show } = useToast();
  const [currentSubmenuItemId, setCurrentSubmenuItemId] = useState<number>();
  const [currentRemoveSubmenuItemId, setCurrentRemoveSubmenuItemId] =
    useState<number>();
  const [form, setForm] = useState<{
    name: string;
    path: string;
    sort: number;
    menuType: TMenuMenuType;
  }>({
    name: '',
    path: '',
    sort: 0,
    menuType: 'LINK',
  });
  const [differenceData, setDifferenceData] = useState<IDifference[]>([]);
  const queryClient = useQueryClient();

  const querySubmenuDetailsQuery = useQuery(
    ['/submenus', currentSubmenuItemId],
    async (context) => {
      return (await querySubmenuDetails({
        id: context.queryKey[1] + '',
      })) as ISubmenu;
    },
    {
      enabled: !!currentSubmenuItemId,
    },
  );

  const updateSubmenuMutation = useMutation(
    async (variables: TBody<IUpdateMenuBody>) => {
      await updateSubmenu(variables);
    },
  );
  const removeSubmenuMutation = useMutation(async (variables: TBody<void>) => {
    await removeSubmenu(variables);
    await queryClient.invalidateQueries(['/menus', details.id]);
    await queryClient.invalidateQueries(['/menus', '/client']);
  });

  useEffect(() => {
    if (querySubmenuDetailsQuery.data) {
      const data = querySubmenuDetailsQuery.data;
      setForm({
        name: data.name,
        path: data.path,
        sort: data.sort,
        menuType: data.menuType,
      });
    }
  }, [querySubmenuDetailsQuery.data]);
  useEffect(() => {
    if (querySubmenuDetailsQuery.data) {
      const data = querySubmenuDetailsQuery.data;
      const differences = diff(
        {
          name: data.name,
          path: data.path,
          sort: data.sort,
          menuType: data.menuType,
        },
        form,
      );
      setDifferenceData(differences);
    }
  }, [form, querySubmenuDetailsQuery.data]);

  async function onClickRemove(item: ISubmenu) {
    try {
      setCurrentRemoveSubmenuItemId(item.id);

      await removeSubmenuMutation.mutateAsync({
        id: item.id + '',
      });

      if (currentSubmenuItemId === item.id) {
        setCurrentSubmenuItemId(undefined);
        clearData();
      }
      setCurrentRemoveSubmenuItemId(undefined);

      show({
        type: 'SUCCESS',
        message: '删除完成',
      });
    } catch (e) {
      removeSubmenuMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onChangeForm(e: ChangeEvent<HTMLInputElement | HTMLSelectElement>) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'sort') {
      setForm({ ...form, sort: parseInt(value) });
    } else {
      setForm({ ...form, [name]: value });
    }
  }

  async function onSubmit(e: FormEvent<HTMLFormElement>) {
    try {
      e.preventDefault();
      e.stopPropagation();

      if (details.submenus.length === 0) {
        show({
          type: 'PRIMARY',
          message: '暂无子菜单，请尝试新增子菜单',
        });
        return;
      }

      const body = getFilterData(getDiffData(differenceData));
      if (isEmpty(body)) {
        show({
          type: 'SUCCESS',
          message: '保存完成',
        });
        return;
      }

      await updateSubmenuMutation.mutateAsync({
        id: currentSubmenuItemId,
        data: body,
      });

      clearData();
      show({
        type: 'SUCCESS',
        message: '保存完成',
      });
    } catch (e) {
      updateSubmenuMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function clearData() {
    setDifferenceData([]);
  }

  function onChangeDetail(item: ISubmenu) {
    setCurrentSubmenuItemId(item.id);
  }

  return (
    <div className="row">
      <div className="col">
        <div className="vstack gap-4">
          <div className="row">
            <div className="col">
              <div className="table-responsive">
                <table className="table table-hover align-middle">
                  <thead>
                    <tr className="text-nowrap">
                      <th scope="col" className="w-10 fw-normal">
                        ID
                      </th>
                      <th scope="col" className="w-10 fw-normal">
                        名称
                      </th>
                      <th scope="col" className="w-10 fw-normal">
                        路径
                      </th>
                      <th scope="col" className="w-10 fw-normal">
                        排序
                      </th>
                      <th scope="col" className="w-10 fw-normal">
                        类型
                      </th>
                      <th scope="col" className="w-10"></th>
                    </tr>
                  </thead>
                  <tbody>
                    {details.submenus.map((item) => {
                      return (
                        <tr
                          key={item.id}
                          className={classNames('text-nowrap', {
                            'table-active': currentSubmenuItemId === item.id,
                          })}
                        >
                          <td
                            className="cursor-pointer"
                            onClick={onChangeDetail.bind(this, item)}
                          >
                            {item.id}
                          </td>
                          <td
                            className="cursor-pointer"
                            onClick={onChangeDetail.bind(this, item)}
                          >
                            {item.name}
                          </td>
                          <td
                            className="cursor-pointer"
                            onClick={onChangeDetail.bind(this, item)}
                          >
                            {item.path}
                          </td>
                          <td
                            className="cursor-pointer"
                            onClick={onChangeDetail.bind(this, item)}
                          >
                            {item.sort}
                          </td>
                          <td
                            className="cursor-pointer"
                            onClick={onChangeDetail.bind(this, item)}
                          >
                            {MENU_TYPE_KEY[item.menuType]}
                          </td>
                          <td>
                            <button
                              disabled={
                                currentRemoveSubmenuItemId === item.id &&
                                removeSubmenuMutation.isLoading
                              }
                              onClick={onClickRemove.bind(this, item)}
                              className="btn btn-sm btn-danger"
                              type="button"
                            >
                              {currentRemoveSubmenuItemId === item.id &&
                              removeSubmenuMutation.isLoading ? (
                                <span
                                  className="spinner-border spinner-border-sm me-2"
                                  role="status"
                                  aria-hidden="true"
                                ></span>
                              ) : (
                                <i className="bi bi-trash me-2"></i>
                              )}
                              删除
                            </button>
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>

              {details.submenus.length === 0 && (
                <div className="text-muted mb-4">暂无子菜单</div>
              )}
            </div>
          </div>

          <form onSubmit={onSubmit} className="vstack gap-4">
            <div>
              <label className="form-label">名称</label>
              <input
                type="text"
                className="form-control"
                name="name"
                value={form.name}
                onChange={onChangeForm}
                aria-describedby="name"
                placeholder="请输入菜单名称"
              />
            </div>

            <div>
              <label className="form-label">路径</label>
              <input
                type="text"
                className="form-control"
                name="path"
                value={form.path}
                onChange={onChangeForm}
                aria-describedby="path"
                placeholder="请输入菜单路径"
              />
            </div>

            <div>
              <label className="form-label">排序</label>
              <input
                type="number"
                className="form-control"
                min={0}
                name="sort"
                value={form.sort}
                onChange={onChangeForm}
                aria-describedby="sort"
                placeholder="请输入菜单排序，最小值为 0"
              />
            </div>

            <div>
              <label className="form-label">类型</label>
              <select
                name="menuType"
                value={form.menuType}
                onChange={onChangeForm}
                className="form-select"
                aria-label="菜单类型"
                placeholder="请选择菜单类型"
              >
                <option>请选择菜单类型</option>
                <option value="LINK">链接</option>
                <option value="BUTTON">按钮</option>
              </select>
            </div>

            <button
              type="submit"
              disabled={updateSubmenuMutation.isLoading}
              className="btn btn-success w-25 my-4"
            >
              {updateSubmenuMutation.isLoading && (
                <span
                  className="spinner-border spinner-border-sm me-2"
                  role="status"
                  aria-hidden="true"
                ></span>
              )}
              更新
            </button>
          </form>
        </div>
      </div>
    </div>
  );
}
